#pragma once

#include <vector>
#include <cstddef>
#include <memory>
#include <mutex>
#include <cassert>

namespace utils {

/**
 * @brief 高性能内存池实现
 * 
 * 这个内存池专门用于管理固定大小对象的快速分配和释放，
 * 适用于高频交易系统中频繁创建和销毁的对象（如MarketData）。
 * 
 * 特点：
 * - 预分配内存块，避免频繁的系统内存分配
 * - 使用空闲链表管理未使用的内存块
 * - 支持自动扩容
 * - 线程安全
 * 
 * @tparam T 要管理的对象类型
 * @tparam BlockSize 每个内存块包含的对象数量
 */
template<typename T, size_t BlockSize = 4096>
class MemoryPool {
    static_assert(BlockSize > 0, "BlockSize must be positive");
    
    // 内存块结构
    struct Block {
        std::vector<T> data;
        std::vector<size_t> free_list;
        size_t next_free;

        Block() : data(BlockSize), next_free(0) {
            free_list.resize(BlockSize);
            for (size_t i = 0; i < BlockSize; ++i) {
                free_list[i] = i;
            }
        }
    };

public:
    /**
     * @brief 构造函数
     * @param initial_blocks 初始内存块数量
     */
    explicit MemoryPool(size_t initial_blocks = 1)
        : total_allocated_(0)
        , total_freed_(0) {
        blocks_.reserve(initial_blocks);
        for (size_t i = 0; i < initial_blocks; ++i) {
            blocks_.emplace_back(std::make_unique<Block>());
        }
    }

    /**
     * @brief 分配一个对象
     * @return 指向分配对象的指针
     */
    T* allocate() {
        std::lock_guard<std::mutex> lock(mutex_);
        
        // 查找有空闲空间的块
        for (auto& block : blocks_) {
            if (block->next_free < BlockSize) {
                size_t index = block->free_list[block->next_free++];
                ++total_allocated_;
                return &block->data[index];
            }
        }

        // 所有块都满了，创建新块
        blocks_.emplace_back(std::make_unique<Block>());
        auto& new_block = blocks_.back();
        size_t index = new_block->free_list[new_block->next_free++];
        ++total_allocated_;
        return &new_block->data[index];
    }

    /**
     * @brief 释放一个对象
     * @param ptr 要释放的对象指针
     */
    void deallocate(T* ptr) {
        if (!ptr) return;

        std::lock_guard<std::mutex> lock(mutex_);
        
        // 查找指针所属的块
        for (auto& block : blocks_) {
            T* begin = &block->data[0];
            T* end = begin + BlockSize;
            
            if (ptr >= begin && ptr < end) {
                size_t index = ptr - begin;
                assert(index < BlockSize);
                assert(block->next_free > 0);
                
                block->free_list[--block->next_free] = index;
                ++total_freed_;
                return;
            }
        }
        
        assert(false && "Invalid pointer passed to deallocate");
    }

    /**
     * @brief 创建一个对象（就地构造）
     * @tparam Args 构造函数参数类型
     * @param args 构造函数参数
     * @return 指向新创建对象的指针
     */
    template<typename... Args>
    T* create(Args&&... args) {
        T* ptr = allocate();
        new (ptr) T(std::forward<Args>(args)...);
        return ptr;
    }

    /**
     * @brief 销毁一个对象（调用析构函数并释放内存）
     * @param ptr 要销毁的对象指针
     */
    void destroy(T* ptr) {
        if (!ptr) return;
        ptr->~T();
        deallocate(ptr);
    }

    /**
     * @brief 获取统计信息
     * @return std::pair<size_t, size_t> {已分配对象数, 已释放对象数}
     */
    std::pair<size_t, size_t> getStats() const {
        std::lock_guard<std::mutex> lock(mutex_);
        return {total_allocated_, total_freed_};
    }

    /**
     * @brief 获取当前内存块数量
     */
    size_t getBlockCount() const {
        std::lock_guard<std::mutex> lock(mutex_);
        return blocks_.size();
    }

    /**
     * @brief 清理所有未使用的内存块
     * 
     * 注意：这个操作可能比较耗时，应该在非关键路径上调用
     */
    void shrink() {
        std::lock_guard<std::mutex> lock(mutex_);
        
        // 移除所有完全未使用的块（除了第一个）
        if (blocks_.size() > 1) {
            auto it = std::remove_if(blocks_.begin() + 1, blocks_.end(),
                [](const auto& block) {
                    return block->next_free == 0;
                });
            blocks_.erase(it, blocks_.end());
        }
    }

private:
    std::vector<std::unique_ptr<Block>> blocks_;
    size_t total_allocated_;
    size_t total_freed_;
    mutable std::mutex mutex_;
};

} // namespace utils